home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / SkinnedMesh / mdraw.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  19.1 KB  |  565 lines

  1. //-----------------------------------------------------------------------------
  2. // File: mdraw.cpp
  3. //
  4. // Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
  5. //-----------------------------------------------------------------------------
  6.  
  7. #include <d3d8.h>
  8. #include <d3dx8.h>
  9. #include "D3DApp.h"
  10. #include "D3DFont.h"
  11. #include "D3DUtil.h"
  12. #include "DXUtil.h"
  13. #include "SkinnedMesh.h"
  14.  
  15.  
  16. HRESULT CMyD3DApplication::DrawMeshContainer(SMeshContainer *pmcMesh)
  17. {
  18.     UINT ipattr;
  19.     HRESULT hr = S_OK;
  20.     LPD3DXBONECOMBINATION pBoneComb;
  21.     DWORD AttribIdPrev;
  22.  
  23.     if (pmcMesh->m_pSkinMesh)
  24.     {
  25.         if (m_method != pmcMesh->m_Method)
  26.         {
  27.             GenerateMesh(pmcMesh);
  28.         }
  29.  
  30.         if (m_method == D3DNONINDEXED)
  31.         {
  32.             AttribIdPrev = UNUSED32; 
  33.             pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pmcMesh->m_pBoneCombinationBuf->GetBufferPointer());
  34.             // Draw using default vtx processing of the device (typically HW)
  35.             for (ipattr = 0; ipattr < pmcMesh->cpattr; ipattr++)
  36.             {
  37.                 DWORD numBlend = 0;
  38.                 for (DWORD i = 0; i < pmcMesh->m_maxFaceInfl; ++i)
  39.                 {
  40.                     if (pBoneComb[ipattr].BoneId[i] != UINT_MAX)
  41.                     {
  42.                         numBlend = i;
  43.                     }
  44.                 }
  45.  
  46.                 if (m_d3dCaps.MaxVertexBlendMatrices >= numBlend + 1)
  47.                 {
  48.                     for (DWORD i = 0; i < pmcMesh->m_maxFaceInfl; ++i)
  49.                     {
  50.                         DWORD matid = pBoneComb[ipattr].BoneId[i];
  51.                         if (matid != UINT_MAX)
  52.                         {
  53.                             m_pd3dDevice->SetTransform(D3DTS_WORLDMATRIX(i), pmcMesh->m_pBoneMatrix[matid]);
  54.                             m_pd3dDevice->MultiplyTransform(D3DTS_WORLDMATRIX(i), &pmcMesh->m_pBoneOffsetMat[matid]);
  55.                         }
  56.                     }
  57.  
  58.                     m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, numBlend);
  59.  
  60.                     if ((AttribIdPrev != pBoneComb[ipattr].AttribId) || (AttribIdPrev == UNUSED32))
  61.                     {
  62.                         m_pd3dDevice->SetMaterial(&(pmcMesh->rgMaterials[pBoneComb[ipattr].AttribId]));
  63.                         m_pd3dDevice->SetTexture(0, pmcMesh->pTextures[pBoneComb[ipattr].AttribId]);
  64.                         AttribIdPrev = pBoneComb[ipattr].AttribId;
  65.                     }
  66.  
  67.                     hr = pmcMesh->pMesh->DrawSubset( ipattr );
  68.                     if(FAILED(hr))
  69.                         return hr;
  70.                 }
  71.  
  72.             }
  73.  
  74.             // If necessary, draw parts that HW could not handle using SW
  75.             if (pmcMesh->iAttrSplit < pmcMesh->cpattr)
  76.             {
  77.                 AttribIdPrev = UNUSED32; 
  78.                 m_pd3dDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, TRUE);
  79.                 for (ipattr = pmcMesh->iAttrSplit; ipattr < pmcMesh->cpattr; ipattr++)
  80.                 {
  81.                     DWORD numBlend = 0;
  82.                     for (DWORD i = 0; i < pmcMesh->m_maxFaceInfl; ++i)
  83.                     {
  84.                         if (pBoneComb[ipattr].BoneId[i] != UINT_MAX)
  85.                         {
  86.                             numBlend = i;
  87.                         }
  88.                     }
  89.  
  90.                     if (m_d3dCaps.MaxVertexBlendMatrices < numBlend + 1)
  91.                     {
  92.                         for (DWORD i = 0; i < pmcMesh->m_maxFaceInfl; ++i)
  93.                         {
  94.                             DWORD matid = pBoneComb[ipattr].BoneId[i];
  95.                             if (matid != UINT_MAX)
  96.                             {
  97.                                 m_pd3dDevice->SetTransform(D3DTS_WORLDMATRIX(i), pmcMesh->m_pBoneMatrix[matid]);
  98.                                 m_pd3dDevice->MultiplyTransform(D3DTS_WORLDMATRIX(i), &pmcMesh->m_pBoneOffsetMat[matid]);
  99.                             }
  100.                         }
  101.  
  102.                         m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, numBlend);
  103.  
  104.                         if ((AttribIdPrev != pBoneComb[ipattr].AttribId) || (AttribIdPrev == UNUSED32))
  105.                         {
  106.                             m_pd3dDevice->SetMaterial(&(pmcMesh->rgMaterials[pBoneComb[ipattr].AttribId]));
  107.                             m_pd3dDevice->SetTexture(0, pmcMesh->pTextures[pBoneComb[ipattr].AttribId]);
  108.                             AttribIdPrev = pBoneComb[ipattr].AttribId;
  109.                         }
  110.  
  111.                         hr = pmcMesh->pMesh->DrawSubset( ipattr );
  112.                         if(FAILED(hr))
  113.                             return hr;
  114.                     }
  115.                 }
  116.                 m_pd3dDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
  117.             }
  118.             m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
  119.         }
  120.         else if (m_method == D3DINDEXEDVS)
  121.         {
  122.             // Use COLOR instead of UBYTE4 since Geforce3 does not support it
  123.             // vConst.w should be 3, but due to about hack, mul by 255 and add epsilon
  124.             D3DXVECTOR4 vConst( 1.0f, 0.0f, 0.0f, 765.01f );
  125.             LPDIRECT3DVERTEXBUFFER8 pVB;
  126.             LPDIRECT3DINDEXBUFFER8 pIB;
  127.  
  128.             if (pmcMesh->m_bUseSW)
  129.             {
  130.                 m_pd3dDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, TRUE);
  131.             }
  132.  
  133.             pmcMesh->pMesh->GetVertexBuffer(&pVB);
  134.             pmcMesh->pMesh->GetIndexBuffer(&pIB);
  135.             hr = m_pd3dDevice->SetStreamSource(0, pVB, D3DXGetFVFVertexSize(pmcMesh->pMesh->GetFVF()));
  136.             if(FAILED(hr))
  137.                 return hr;
  138.             hr = m_pd3dDevice->SetIndices(pIB, 0);
  139.             if(FAILED(hr))
  140.                 return hr;
  141.             pVB->Release();
  142.             pIB->Release();
  143.  
  144.             hr = m_pd3dDevice->SetVertexShader(m_dwIndexedVertexShader[pmcMesh->m_maxFaceInfl - 1]);
  145.             if(FAILED(hr))
  146.                 return hr;
  147.  
  148.             pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pmcMesh->m_pBoneCombinationBuf->GetBufferPointer());
  149.             for (ipattr = 0; ipattr < pmcMesh->cpattr; ipattr++)
  150.             {
  151.                 for (DWORD i = 0; i < pmcMesh->m_paletteSize; ++i)
  152.                 {
  153.                     DWORD matid = pBoneComb[ipattr].BoneId[i];
  154.                     if (matid != UINT_MAX)
  155.                     {
  156.                         D3DXMATRIXA16 mat;
  157.                         D3DXMatrixMultiply(&mat, &pmcMesh->m_pBoneOffsetMat[matid], pmcMesh->m_pBoneMatrix[matid]);
  158.                         D3DXMatrixMultiplyTranspose(&mat, &mat, &m_mView);
  159.                         m_pd3dDevice->SetVertexShaderConstant(i*3 + 9, &mat, 3);
  160.                     }
  161.                 }
  162.  
  163.                 // Sum of all ambient and emissive contribution
  164.                 D3DXCOLOR ambEmm;
  165.                 D3DXColorModulate(&ambEmm, &D3DXCOLOR(pmcMesh->rgMaterials[pBoneComb[ipattr].AttribId].Ambient),&D3DXCOLOR(.25, .25, .25, 1.0));
  166.                 ambEmm += D3DXCOLOR(pmcMesh->rgMaterials[pBoneComb[ipattr].AttribId].Emissive);
  167.                 m_pd3dDevice->SetVertexShaderConstant(8, &(pmcMesh->rgMaterials[pBoneComb[ipattr].AttribId].Diffuse), 1);
  168.                 m_pd3dDevice->SetVertexShaderConstant(7, &ambEmm, 1);
  169.                 vConst.y = pmcMesh->rgMaterials[pBoneComb[ipattr].AttribId].Power;
  170.                 m_pd3dDevice->SetVertexShaderConstant(0, &vConst, 1);
  171.  
  172.                 m_pd3dDevice->SetTexture(0, pmcMesh->pTextures[pBoneComb[ipattr].AttribId]);
  173.  
  174.                 hr = m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 
  175.                                              pBoneComb[ipattr].VertexStart, pBoneComb[ipattr].VertexCount,
  176.                                              pBoneComb[ipattr].FaceStart * 3, pBoneComb[ipattr].FaceCount);
  177.                 if(FAILED(hr))
  178.                     return hr;
  179.             }
  180.  
  181.             if (pmcMesh->m_bUseSW)
  182.             {
  183.                 m_pd3dDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
  184.             }
  185.         }
  186.         else if (m_method == D3DINDEXED)
  187.         {
  188.             if (pmcMesh->m_bUseSW)
  189.             {
  190.                 m_pd3dDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, TRUE);
  191.             }
  192.  
  193.             if (pmcMesh->m_maxFaceInfl == 1)
  194.                 m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_0WEIGHTS);
  195.             else
  196.                 m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, pmcMesh->m_maxFaceInfl - 1);
  197.             if (pmcMesh->m_maxFaceInfl)
  198.                 m_pd3dDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE);
  199.             pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pmcMesh->m_pBoneCombinationBuf->GetBufferPointer());
  200.             for (ipattr = 0; ipattr < pmcMesh->cpattr; ipattr++)
  201.             {
  202.                 for (DWORD i = 0; i < pmcMesh->m_paletteSize; ++i)
  203.                 {
  204.                     DWORD matid = pBoneComb[ipattr].BoneId[i];
  205.                     if (matid != UINT_MAX)
  206.                     {
  207.                         m_pd3dDevice->SetTransform(D3DTS_WORLDMATRIX(i), pmcMesh->m_pBoneMatrix[matid]);
  208.                         m_pd3dDevice->MultiplyTransform(D3DTS_WORLDMATRIX(i), &pmcMesh->m_pBoneOffsetMat[matid]);
  209.                     }
  210.                 }
  211.                 
  212.                 m_pd3dDevice->SetMaterial(&(pmcMesh->rgMaterials[pBoneComb[ipattr].AttribId]));
  213.                 m_pd3dDevice->SetTexture(0, pmcMesh->pTextures[pBoneComb[ipattr].AttribId]);
  214.  
  215.                 hr = pmcMesh->pMesh->DrawSubset( ipattr );
  216.                 if(FAILED(hr))
  217.                     return hr;
  218.             }
  219.             m_pd3dDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
  220.             m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
  221.  
  222.             if (pmcMesh->m_bUseSW)
  223.             {
  224.                 m_pd3dDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
  225.             }
  226.         }
  227.         else if (m_method == SOFTWARE)
  228.         {
  229.             D3DXMATRIX  Identity;
  230.             DWORD       cBones  = pmcMesh->m_pSkinMesh->GetNumBones();
  231.  
  232.             // set up bone transforms
  233.             for (DWORD iBone = 0; iBone < cBones; ++iBone)
  234.             {
  235.                 D3DXMatrixMultiply
  236.                 (
  237.                     &m_pBoneMatrices[iBone],                 // output
  238.                     &pmcMesh->m_pBoneOffsetMat[iBone], 
  239.                     pmcMesh->m_pBoneMatrix[iBone]
  240.                 );
  241.             }
  242.  
  243.             // set world transform
  244.             D3DXMatrixIdentity(&Identity);
  245.             hr = m_pd3dDevice->SetTransform(D3DTS_WORLD, &Identity);
  246.             if (FAILED(hr))
  247.                 return hr;
  248.  
  249.             // generate skinned mesh
  250.             hr = pmcMesh->m_pSkinMesh->UpdateSkinnedMesh(m_pBoneMatrices, NULL, pmcMesh->pMesh);
  251.             if (FAILED(hr))
  252.                 return hr;
  253.  
  254.             for (ipattr = 0; ipattr < pmcMesh->cpattr; ipattr++)
  255.             {
  256.                 m_pd3dDevice->SetMaterial(&(pmcMesh->rgMaterials[pmcMesh->m_pAttrTable[ipattr].AttribId]));
  257.                 m_pd3dDevice->SetTexture(0, pmcMesh->pTextures[pmcMesh->m_pAttrTable[ipattr].AttribId]);
  258.                 hr  = pmcMesh->pMesh->DrawSubset(pmcMesh->m_pAttrTable[ipattr].AttribId);
  259.                 if (FAILED(hr))
  260.                     return hr;
  261.             }
  262.             return hr;
  263.         }
  264.     }
  265.     else
  266.     {
  267.         for (ipattr = 0; ipattr < pmcMesh->cpattr; ipattr++)
  268.         {
  269.             m_pd3dDevice->SetMaterial(&(pmcMesh->rgMaterials[ipattr]));
  270.             m_pd3dDevice->SetTexture(0, pmcMesh->pTextures[ipattr]);
  271.             hr = pmcMesh->pMesh->DrawSubset( ipattr );
  272.             if(FAILED(hr))
  273.                 return hr;
  274.         }
  275.     }
  276.  
  277.     return S_OK;
  278. }
  279.  
  280.  
  281.  
  282.  
  283. HRESULT CMyD3DApplication::UpdateFrames(SFrame *pframeCur, D3DXMATRIX &matCur)
  284. {
  285.     HRESULT hr = S_OK;
  286.     pframeCur->matCombined = matCur;
  287.     D3DXMatrixMultiply(&pframeCur->matCombined, &pframeCur->matRot, &matCur);
  288.     D3DXMatrixMultiply(&pframeCur->matCombined, &pframeCur->matCombined, &pframeCur->matTrans );
  289.     SFrame *pframeChild = pframeCur->pframeFirstChild;
  290.     while (pframeChild != NULL)
  291.     {
  292.         hr = UpdateFrames(pframeChild, pframeCur->matCombined);
  293.         if (FAILED(hr))
  294.             return hr;
  295.  
  296.         pframeChild = pframeChild->pframeSibling;
  297.     }
  298.     return S_OK;
  299. }
  300.  
  301.  
  302.  
  303.  
  304. HRESULT CMyD3DApplication::DrawFrames(SFrame *pframeCur, UINT &cTriangles)
  305. {
  306.     HRESULT hr = S_OK;
  307.     SMeshContainer *pmcMesh;
  308.     SFrame *pframeChild;
  309.  
  310.     if (pframeCur->pmcMesh != NULL)
  311.     {
  312.         hr = m_pd3dDevice->SetTransform(D3DTS_WORLD, &pframeCur->matCombined);
  313.         if(FAILED(hr))
  314.             return hr;
  315.     }
  316.  
  317.     pmcMesh = pframeCur->pmcMesh;
  318.     while (pmcMesh != NULL)
  319.     {
  320.         hr = DrawMeshContainer(pmcMesh);
  321.         if (FAILED(hr))
  322.             return hr;
  323.  
  324.         cTriangles += pmcMesh->pMesh->GetNumFaces();
  325.  
  326.         pmcMesh = pmcMesh->pmcNext;
  327.     }
  328.  
  329.     pframeChild = pframeCur->pframeFirstChild;
  330.     while (pframeChild != NULL)
  331.     {
  332.         hr = DrawFrames(pframeChild, cTriangles);
  333.         if (FAILED(hr))
  334.             return hr;
  335.  
  336.         pframeChild = pframeChild->pframeSibling;
  337.     }
  338.  
  339.     return S_OK;
  340. }
  341.  
  342.  
  343.  
  344.  
  345. void SFrame::SetTime(float fGlobalTime)
  346. {
  347.     UINT iKey;
  348.     UINT dwp2;
  349.     UINT dwp3;
  350.     D3DXMATRIXA16 matResult;
  351.     D3DXMATRIXA16 matTemp;
  352.     float fTime1;
  353.     float fTime2;
  354.     float fLerpValue;
  355.     D3DXVECTOR3 vScale;
  356.     D3DXVECTOR3 vPos;
  357.     D3DXQUATERNION quat;
  358.     BOOL bAnimate = false;
  359.     float fTime;
  360.  
  361.     if (m_pMatrixKeys )
  362.     {
  363.         fTime = (float)fmod(fGlobalTime, m_pMatrixKeys[m_cMatrixKeys-1].dwTime);
  364.  
  365.         for (iKey = 0 ;iKey < m_cMatrixKeys ; iKey++)
  366.         {
  367.             if ((float)m_pMatrixKeys[iKey].dwTime > fTime)
  368.             {
  369.                 dwp3 = iKey;
  370.  
  371.                 if (iKey > 0)
  372.                 {
  373.                     dwp2= iKey - 1;
  374.                 }
  375.                 else  // when iKey == 0, then dwp2 == 0
  376.                 {
  377.                     dwp2 = iKey;
  378.                 }
  379.  
  380.                 break;
  381.             }
  382.         }
  383.         fTime1 = (float)m_pMatrixKeys[dwp2].dwTime;
  384.         fTime2 = (float)m_pMatrixKeys[dwp3].dwTime;
  385.  
  386.         if ((fTime2 - fTime1) ==0)
  387.             fLerpValue = 0;
  388.         else
  389.             fLerpValue =  (fTime - fTime1)  / (fTime2 - fTime1);
  390.  
  391.         if (fLerpValue > 0.5)
  392.         {
  393.             iKey = dwp3;
  394.         }
  395.         else
  396.         {
  397.             iKey = dwp2;
  398.         }
  399.  
  400.         pframeToAnimate->matRot = m_pMatrixKeys[iKey].mat;
  401.     }
  402.     else
  403.     {
  404.         D3DXMatrixIdentity(&matResult);
  405.  
  406.         if (m_pScaleKeys)
  407.         {
  408.             dwp2 = dwp3 = 0;
  409.  
  410.             fTime = (float)fmod(fGlobalTime, m_pScaleKeys[m_cScaleKeys-1].dwTime);
  411.  
  412.             for (iKey = 0 ;iKey < m_cScaleKeys ; iKey++)
  413.             {
  414.                 if ((float)m_pScaleKeys[iKey].dwTime > fTime)
  415.                 {
  416.                     dwp3 = iKey;
  417.  
  418.                     if (iKey > 0)
  419.                     {
  420.                         dwp2= iKey - 1;
  421.                     }
  422.                     else  // when iKey == 0, then dwp2 == 0
  423.                     {
  424.                         dwp2 = iKey;
  425.                     }
  426.  
  427.                     break;
  428.                 }
  429.             }
  430.             fTime1 = (float)m_pScaleKeys[dwp2].dwTime;
  431.             fTime2 = (float)m_pScaleKeys[dwp3].dwTime;
  432.  
  433.             if ((fTime2 - fTime1) ==0)
  434.                 fLerpValue = 0;
  435.             else
  436.                 fLerpValue =  (fTime - fTime1)  / (fTime2 - fTime1);
  437.  
  438.             D3DXVec3Lerp(&vScale,
  439.                     &m_pScaleKeys[dwp2].vScale,
  440.                     &m_pScaleKeys[dwp3].vScale,
  441.                     fLerpValue);
  442.  
  443.  
  444.             D3DXMatrixScaling(&matTemp, vScale.x, vScale.y, vScale.z);
  445.  
  446.             D3DXMatrixMultiply(&matResult, &matResult, &matTemp);
  447.  
  448.             bAnimate = true;
  449.         }
  450.  
  451.         //check rot keys
  452.         if (m_pRotateKeys )
  453.         {
  454.             int i1 = 0;
  455.             int i2 = 0;
  456.  
  457.             fTime = (float)fmod(fGlobalTime, m_pRotateKeys[m_cRotateKeys-1].dwTime);
  458.  
  459.             for (iKey = 0 ;iKey < m_cRotateKeys ; iKey++)
  460.             {
  461.                 if ((float)m_pRotateKeys[iKey].dwTime > fTime)
  462.                 {
  463.                     i1 = (iKey > 0) ? iKey - 1 : 0;
  464.                     i2 = iKey;
  465.                     break;
  466.                 }
  467.             }
  468.  
  469.             fTime1 = (float)m_pRotateKeys[i1].dwTime;
  470.             fTime2 = (float)m_pRotateKeys[i2].dwTime;
  471.  
  472.             if ((fTime2 - fTime1) ==0)
  473.                 fLerpValue = 0;
  474.             else
  475.                 fLerpValue =  (fTime - fTime1)  / (fTime2 - fTime1);
  476.  
  477. #define USE_SQUAD
  478. #ifdef USE_SQUAD
  479.             int i0 = i1 - 1;
  480.             int i3 = i2 + 1;
  481.  
  482.             if(i0 < 0)
  483.                 i0 += m_cRotateKeys;
  484.  
  485.             if(i3 >= (INT) m_cRotateKeys)
  486.                 i3 -= m_cRotateKeys;
  487.  
  488.             D3DXQUATERNION qA, qB, qC;
  489.             D3DXQuaternionSquadSetup(&qA, &qB, &qC, 
  490.                 &m_pRotateKeys[i0].quatRotate, &m_pRotateKeys[i1].quatRotate, 
  491.                 &m_pRotateKeys[i2].quatRotate, &m_pRotateKeys[i3].quatRotate);
  492.  
  493.             D3DXQuaternionSquad(&quat, &m_pRotateKeys[i1].quatRotate, &qA, &qB, &qC, fLerpValue);
  494. #else
  495.             D3DXQuaternionSlerp(&quat, &m_pRotateKeys[i1].quatRotate, &m_pRotateKeys[i2].quatRotate, fLerpValue);
  496. #endif
  497.  
  498.             quat.w = -quat.w;
  499.             D3DXMatrixRotationQuaternion(&matTemp, &quat);
  500.             D3DXMatrixMultiply(&matResult, &matResult, &matTemp);
  501.  
  502.             bAnimate = true;
  503.         }
  504.  
  505.         if (m_pPositionKeys)
  506.         {
  507.             dwp2=dwp3=0;
  508.  
  509.             fTime = (float)fmod(fGlobalTime, m_pPositionKeys[m_cPositionKeys-1].dwTime);
  510.  
  511.             for (iKey = 0 ;iKey < m_cPositionKeys ; iKey++)
  512.             {
  513.                 if ((float)m_pPositionKeys[iKey].dwTime > fTime)
  514.                 {
  515.                     dwp3 = iKey;
  516.  
  517.                     if (iKey > 0)
  518.                     {
  519.                         dwp2= iKey - 1;
  520.                     }
  521.                     else  // when iKey == 0, then dwp2 == 0
  522.                     {
  523.                         dwp2 = iKey;
  524.                     }
  525.  
  526.                     break;
  527.                 }
  528.             }
  529.             fTime1 = (float)m_pPositionKeys[dwp2].dwTime;
  530.             fTime2 = (float)m_pPositionKeys[dwp3].dwTime;
  531.  
  532.             if ((fTime2 - fTime1) ==0)
  533.                 fLerpValue = 0;
  534.             else
  535.                 fLerpValue =  (fTime - fTime1)  / (fTime2 - fTime1);
  536.  
  537.  
  538.             D3DXVec3Lerp((D3DXVECTOR3*)&vPos,
  539.                     &m_pPositionKeys[dwp2].vPos,
  540.                     &m_pPositionKeys[dwp3].vPos,
  541.                     fLerpValue);
  542.  
  543.             D3DXMatrixTranslation(&matTemp, vPos.x, vPos.y, vPos.z);
  544.  
  545.             D3DXMatrixMultiply(&matResult, &matResult, &matTemp);
  546.             bAnimate = true;
  547.         }
  548.         else
  549.         {
  550.             D3DXMatrixTranslation(&matTemp, pframeToAnimate->matRotOrig._41, pframeToAnimate->matRotOrig._42, pframeToAnimate->matRotOrig._43);
  551.  
  552.             D3DXMatrixMultiply(&matResult, &matResult, &matTemp);
  553.         }
  554.  
  555.         if (bAnimate)
  556.         {
  557.             pframeToAnimate->matRot = matResult;
  558.         }
  559.     }
  560. }
  561.  
  562.  
  563.  
  564.  
  565.